package com.nononsenseapps.feeder.ui.common.xpopup

import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import android.view.*
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.gitee.wsl.store.StateSavedVar
import com.gitee.wsl.jvm.store.mmkv.MMKVStoreServer
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.CenterPopupView
import com.lxj.xpopup.impl.InputConfirmPopupView
import com.lxj.xpopup.interfaces.OnCancelListener
import com.lxj.xpopup.interfaces.OnInputConfirmListener
import com.lxj.xpopup.util.XPopupUtils
import com.nononsenseapps.feeder.ui.R
import com.nononsenseapps.feeder.util.PrefUtils
import com.nononsenseapps.feeder.util.isTrue
import com.squareup.moshi.JsonClass

object XPopupExt {
    private fun getDefaultCallBack(propName:String):ConfirmPopupViewItemCallBack{
        return object:ConfirmPopupViewItemCallBack{
            var mutableDefaultList by StateSavedVar(
                MMKVStoreServer.get(),
                propName, ConfirmPopupViewItemList(mutableListOf()))

            override fun getListItemTitle(item: ConfirmPopupViewItem):String {
                return item.title()
            }

            override fun listItems(): List<ConfirmPopupViewItem> {
                return  mutableDefaultList.items
            }

            override fun removeItem(item: ConfirmPopupViewItem) {
                mutableDefaultList.items.remove(item)
                flushList()
            }

            override fun updateItem(item: ConfirmPopupViewItem) {
                flushList()
            }

            override fun addItem(item: ConfirmPopupViewItem) {
                mutableDefaultList.items.add(item)
                flushList()
            }

            fun flushList(){
                mutableDefaultList=ConfirmPopupViewItemList(mutableDefaultList.items)
            }
        }
    }

    fun asInputConfirm(context: Context, title:CharSequence, content:CharSequence, inputContent:CharSequence?=null, hint:CharSequence?=null, storePropName: String, confirmListener: OnInputConfirmListener, cancelListener: OnCancelListener?=null, callBack: ConfirmPopupViewItemCallBack=getDefaultCallBack(storePropName)): InputListConfirmPopupView {
        val popupView = InputListConfirmPopupView(context,callBack)
        popupView.setTitleContent(title, content, hint)
        popupView.inputContent = inputContent
        popupView.setListener(confirmListener, cancelListener)
        return XPopup.Builder(context).isDarkTheme(PrefUtils.isNightMode(context)).isViewMode(true).moveUpToKeyboard(false).asCustom(popupView) as InputListConfirmPopupView
    }

    fun asListConfirm(context: Context, title:CharSequence, confirmListener: OnConfirmListener<ConfirmPopupViewItem>, callBack: ConfirmPopupViewItemCallBack): ListConfirmPopupView {
        val popupView = ListConfirmPopupView(context,callBack)
        popupView.setTitleContent(title)
        popupView.setListener(confirmListener)
        return XPopup.Builder(context).isDarkTheme(PrefUtils.isNightMode(context)).moveUpToKeyboard(false).asCustom(popupView) as ListConfirmPopupView
    }

}

open class  ListConfirmPopupView( context: Context,val callBack: ConfirmPopupViewItemCallBack):CenterPopupView(context) {
    lateinit var recyclerView: RecyclerView
    lateinit var tv_title:TextView

    var title: CharSequence? = null

    var confirmListener: OnConfirmListener<ConfirmPopupViewItem>?=null

    protected val listAdapter =
        object : ListAdapter<ConfirmPopupViewItem, InputListConfirmPopupViewItemViewHolder>(InputListConfirmPopupViewItemDiff()) {
            override fun onCreateViewHolder(
                parent: ViewGroup,
                viewType: Int
            ): InputListConfirmPopupViewItemViewHolder {
                return InputListConfirmPopupViewItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout._xpopup_adapter_text_match, parent, false),callBack=warpCallBack, onClick = {
                    confirmListener?.onConfirm(it)
                    dismiss()
                }, viewModel = !callBack.isEditorModel())
            }

            override fun onBindViewHolder(holder: InputListConfirmPopupViewItemViewHolder, position: Int) {
                holder.initItem(getItem(position))
            }
        }


    private val warpCallBack=object:ConfirmPopupViewItemCallBack{
        override fun getListItemTitle(item: ConfirmPopupViewItem): String {
            return callBack.getListItemTitle(item)
        }

        override fun listItems(): List<ConfirmPopupViewItem> {
            return callBack.listItems()
        }

        override fun removeItem(item: ConfirmPopupViewItem) {
            callBack.removeItem(item)
            updateItem()
        }

        override fun updateItem(item: ConfirmPopupViewItem) {
            callBack.updateItem(item)
            updateItem()
        }

        override fun addItem(item: ConfirmPopupViewItem) {
            callBack.listItems().forEach {
                if(it.value == item.value)
                    return
            }
            callBack.addItem(item)
            updateItem()
        }
    }

    protected lateinit var divider3:View

    override fun onCreate() {
        super.onCreate()

        findViewById<LinearLayout>(R.id.container_input).visibility=View.GONE
        findViewById<LinearLayout>(R.id.container_confirm).visibility=View.GONE

        tv_title=findViewById(R.id.tv_title)

        if (!TextUtils.isEmpty(title)) {
            tv_title.text = title
        } else {
            XPopupUtils.setVisible(tv_title, false)
        }

        recyclerView = findViewById(R.id.recyclerView)
        if (bindLayoutId != 0) {
            recyclerView.layoutManager = LinearLayoutManager(context)
        }
        recyclerView.adapter=listAdapter

        divider3 = findViewById(R.id.xpopup_divider3)

        updateItem()

        applyThemeNew()
    }

    private fun updateItem(){
        listAdapter.submitList(callBack.listItems())
        listAdapter.notifyDataSetChanged()
    }

    override fun getImplLayoutId():Int {
        return  R.layout._xpopup_center_impl_list_confirm
    }

    override fun applyTheme() {
    }

    private fun applyThemeNew() {
        if (popupInfo.isDarkTheme) {
            applyDarkTheme()
        } else {
            applyLightTheme()
        }
    }

    override fun applyDarkTheme() {
        super.applyDarkTheme()
        divider3.setBackgroundColor(resources.getColor(com.lxj.xpopup.R.color._xpopup_list_dark_divider))
    }

    override fun applyLightTheme() {
        super.applyLightTheme()
        divider3.setBackgroundColor(resources.getColor(com.lxj.xpopup.R.color._xpopup_list_divider))
    }

     fun setListener(
        confirmListener: OnConfirmListener<ConfirmPopupViewItem>?
    ) {
         this.confirmListener=confirmListener
        /*super.setListener({ text ->
            text?.isNotEmpty().isTrue {
                warpCallBack.addItem(ConfirmPopupViewItem(text))
                inputConfirmListener?.onConfirm(text)
            }
        }, cancelListener)*/
    }

    fun setTitleContent(title: CharSequence) {
        this.title=title
    }
}

@SuppressLint("ViewConstructor")
open class InputListConfirmPopupView(context: Context, val callBack: ConfirmPopupViewItemCallBack): InputConfirmPopupView(context, 0) {
    lateinit var recyclerView: RecyclerView
    protected val listAdapter =
        object : ListAdapter<ConfirmPopupViewItem, InputListConfirmPopupViewItemViewHolder>(InputListConfirmPopupViewItemDiff()) {
            override fun onCreateViewHolder(
                parent: ViewGroup,
                viewType: Int
            ): InputListConfirmPopupViewItemViewHolder {
                return InputListConfirmPopupViewItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout._xpopup_adapter_text_match, parent, false),callBack=warpCallBack, onClick = {
                    editText.setText(it.value)
                }, viewModel = !callBack.isEditorModel())
            }

            override fun onBindViewHolder(holder: InputListConfirmPopupViewItemViewHolder, position: Int) {
                holder.initItem(getItem(position))
            }
        }


    private val warpCallBack=object:ConfirmPopupViewItemCallBack{
        override fun getListItemTitle(item: ConfirmPopupViewItem): String {
            return callBack.getListItemTitle(item)
        }

        override fun listItems(): List<ConfirmPopupViewItem> {
            return callBack.listItems()
        }

        override fun removeItem(item: ConfirmPopupViewItem) {
            callBack.removeItem(item)
            updateItem()
        }

        override fun updateItem(item: ConfirmPopupViewItem) {
            callBack.updateItem(item)
            updateItem()
        }

        override fun addItem(item: ConfirmPopupViewItem) {
            callBack.listItems().forEach {
                if(it.value == item.value)
                    return
            }
            callBack.addItem(item)
            updateItem()
        }
    }

    protected lateinit var divider3:View

    override fun onCreate() {
        super.onCreate()
        recyclerView = findViewById(R.id.recyclerView)
        if (bindLayoutId != 0) {
            recyclerView.layoutManager = LinearLayoutManager(context)
        }
        recyclerView.adapter=listAdapter

        divider3 = findViewById(R.id.xpopup_divider3)

        updateItem()

        applyThemeNew()
    }

    private fun updateItem(){
        listAdapter.submitList(callBack.listItems())
        listAdapter.notifyDataSetChanged()
    }

    override fun getImplLayoutId():Int {
        return  R.layout._xpopup_center_impl_list_confirm;
    }

    override fun applyTheme() {
    }

    private fun applyThemeNew() {
        if (popupInfo.isDarkTheme) {
            applyDarkTheme()
        } else {
            applyLightTheme()
        }
    }

    override fun applyDarkTheme() {
        super.applyDarkTheme()
        divider3.setBackgroundColor(resources.getColor(com.lxj.xpopup.R.color._xpopup_list_dark_divider))
    }

    override fun applyLightTheme() {
        super.applyLightTheme()
        divider3.setBackgroundColor(resources.getColor(com.lxj.xpopup.R.color._xpopup_list_divider))
    }

    override fun setListener(
        inputConfirmListener: OnInputConfirmListener?,
        cancelListener: OnCancelListener?
    ) {
        super.setListener({ text ->
            text?.isNotEmpty().isTrue {
                warpCallBack.addItem(ConfirmPopupViewItem(text))
              inputConfirmListener?.onConfirm(text)
            }
        }, cancelListener)
    }
}

class InputListConfirmPopupViewItemViewHolder(val parent: View,val callBack: ConfirmPopupViewItemCallBack,val onClick:(ConfirmPopupViewItem)->Unit,val viewModel:Boolean=false): RecyclerView.ViewHolder(parent) , View.OnClickListener,View.OnCreateContextMenuListener{
    val imageView:ImageView=parent.findViewById(R.id.iv_image)
    val text:TextView=parent.findViewById( R.id.tv_text)

    var item:ConfirmPopupViewItem?=null

    init {
        imageView.visibility = View.GONE
        parent.setOnClickListener(this)
        if(!viewModel)
            parent.setOnCreateContextMenuListener(this)
    }

    fun initItem(item: ConfirmPopupViewItem){
        this.item=item
        text.text=callBack.getListItemTitle(item)
    }

    override fun onClick(v: View?) {
        onClick(item!!)
    }

    override fun onCreateContextMenu(
        menu: ContextMenu?,
        v: View?,
        menuInfo: ContextMenu.ContextMenuInfo?
    ) {
        v?.context?.let { context ->
            if (menu != null) {
                MenuInflater(context).inflate(R.menu.popmenu_confirm_list_item, menu)
                menu.findItem(R.id.action_delete).setOnMenuItemClickListener {
                    callBack.removeItem(item!!)
                    true
                }
                menu.findItem(R.id.action_change_title).setOnMenuItemClickListener {
                    XPopup.Builder(context)
                        .asInputConfirm("修改名称", "请输入新名称。") {
                            it.isNotEmpty().isTrue {
                                item!!.key=it
                                callBack.updateItem(item!!)
                            }
                        }.show()
                    true
                }
            }
        }
    }
}

class InputListConfirmPopupViewItemDiff: DiffUtil.ItemCallback<ConfirmPopupViewItem>() {
    override fun areItemsTheSame(
        oldItem: ConfirmPopupViewItem,
        newItem: ConfirmPopupViewItem
    ): Boolean {
        return oldItem.value==newItem.value
    }

    override fun areContentsTheSame(
        oldItem: ConfirmPopupViewItem,
        newItem: ConfirmPopupViewItem
    ): Boolean {
        return  oldItem.value==newItem.value&&oldItem.key==newItem.key&&oldItem.selected==newItem.selected
    }
}

@JsonClass(generateAdapter = true)
data class ConfirmPopupViewItem(var key:String, val value:String=key, val selected:Boolean=false){
    fun title():String{
        if(key == value)
            return key
        return "$key->$value"
    }

    fun toPair()=Pair(key,value)
}

@JsonClass(generateAdapter = true)
data class ConfirmPopupViewItemList(val items:MutableList<ConfirmPopupViewItem>)

interface OnConfirmListener<ConfirmPopupViewItem> {
    fun onConfirm(item: ConfirmPopupViewItem)
}

interface ConfirmPopupViewItemCallBack{

    fun getListItemTitle(item: ConfirmPopupViewItem):String

    fun listItems():List<ConfirmPopupViewItem>

    //fun selectItem(item: ConfirmPopupViewItem)

    fun removeItem(item: ConfirmPopupViewItem)

    fun updateItem(item: ConfirmPopupViewItem)

    fun addItem(item: ConfirmPopupViewItem)

    fun isEditorModel():Boolean=true
}
